import { useMenuStore, useTabStore, useConfigStore, useDialogStore } from '@/stores'
import { useRouter, useRoute } from 'vue-router'
import { useAsyncState, useDebounceFn } from '@vueuse/core'
import { ElNotification, type UploadRawFile } from 'element-plus'
import type { UserListItemResponseData, ConfigUserStatusValueType } from '@/types/api'
import { getUserList, getRoleList, addUser, deleteUser, getUser, updateUser } from '@/api'
import { ConfigImageExts, ConfigImageSize } from '@/config'
import type { UserItemRequestData } from '@/types/api'

const statusColorMap = {
  All: '#909399',
  Active: '#409eff',
  Pending: '#e6a23c',
  Banned: '#f56c6c',
  Rejected: '#f56c6c'
}
export const userStatusList = () => {
  const router = useRouter()
  const menuStore = useMenuStore()
  const tabStore = useTabStore()
  const configStore = useConfigStore()
  const dialogStore = useDialogStore()
  const page = ref(1)
  const size = ref(20)
  const tabValue = ref<ConfigUserStatusValueType>('All')
  const selectValues = ref<string[]>([])
  const keywordValue = ref('')

  const status = ref(
    Object.keys(statusColorMap).map((key) => ({
      color: statusColorMap[key as ConfigUserStatusValueType],
      badgeValue: 0,
      ...configStore.getUserStatus(key as ConfigUserStatusValueType)
    }))
  )

  const { state: selectOptions } = useAsyncState(
    () =>
      getRoleList().then((roles) => roles.map((role) => ({ label: role.name, value: role.code }))),
    []
  )

  // 问题：useDebounceFn(() => getUserList(page.value, size.value, tabValue.value, selectValues.value, keywordValue.value),500)
  // 为什么直接使用防抖函数不可以，原因是防抖函数返回的 promise 对象，属于异步了
  // 而 watchEffect 只能监听同步的数据变化，无法监听异步中的数据变化
  // 解决办法：将需要依赖监听的数据提取出来，watchEffect通过同步方式传入到异步函数中去即可

  const { state, isLoading, execute } = useAsyncState(
    (
      page: number,
      size: number,
      tabValue: ConfigUserStatusValueType,
      selectValues: string[],
      keywordValue: string
    ) =>
      getUserList(page, size, tabValue, selectValues, keywordValue).then((data) => {
        Object.entries(data.status).forEach(([key, badgeValue]) => {
          const sta = status.value.find((sta) => sta.value === key)
          if (sta) {
            sta.badgeValue = badgeValue
          }
        })
        return data
      }),
    {
      total: 0,
      data: [],
      status: {
        All: 0,
        Active: 0,
        Pending: 0,
        Banned: 0,
        Rejected: 0
      }
    },
    { resetOnExecute: false, immediate: false }
  )

  let execute2 = (
    page: number,
    size: number,
    tabValue: ConfigUserStatusValueType,
    selectValues: string[],
    keywordValue: string
  ) => {
    execute(0, page, size, tabValue, selectValues, keywordValue)
    execute2 = useDebounceFn(
      (
        page: number,
        size: number,
        tabValue: ConfigUserStatusValueType,
        selectValues: string[],
        keywordValue: string
      ) => execute(0, page, size, tabValue, selectValues, keywordValue),
      500
    )
  }

  // 问题：调用 execute 导致分页数据混乱
  // 原因：调用 execute 会将 state.value = initialState 重新初始化，导致 data 为 []
  // 这时候虽然跳转到 page = 2 了，但是由于数据 data = []，el-pagination 分页组件自动将 page = 1
  // 所以就出现点击 page = 2 一下子就变成了 page = 1 了
  // 解决方案：resetOnExecute: false 配置为 false，那么 execute 就不会再重新初始化了
  watchEffect(() => {
    isLoading.value = true
    execute2(page.value, size.value, tabValue.value, selectValues.value, keywordValue.value)
  })

  const onAdd = () => {
    const menuName = 'user'
    const tabName = 'user-save'
    tabStore.push({
      title: '用户新增',
      icon: 'Plus',
      name: tabName,
      source: 'button',
      menu: menuName,
      query: {}
    })
    menuStore.menuActive = menuName
    tabStore.tabActive = tabName
    router.push({ name: tabName })
  }

  const onDelete = (row: UserListItemResponseData) => {
    dialogStore.open(
      '删除提示',
      '确定要删除吗？',
      [
        { type: 'danger', label: '删除' },
        { type: 'default', label: '取消' }
      ],
      ($index) => {
        if ($index !== 0) {
          dialogStore.close()
          return
        }

        deleteUser(row.id).then(() => {
          dialogStore.close()
          ElNotification({
            message: '删除成功',
            type: 'success'
          })
          execute(0, page.value, size.value, tabValue.value, selectValues.value, keywordValue.value)
        })
      }
    )
  }

  const onEdit = (row: UserListItemResponseData) => {
    const menuName = 'user'
    const tabName = 'user-save'
    tabStore.push({
      title: '用户修改',
      icon: 'Edit',
      name: tabName,
      source: 'button',
      menu: menuName,
      query: { id: row.id }
    })
    menuStore.menuActive = menuName
    tabStore.tabActive = tabName
    router.push({ name: tabName, query: { id: row.id } })
  }

  return {
    tabValue,
    page,
    size,
    selectValues,
    keywordValue,
    isLoading,
    selectOptions,
    state,
    status,
    onAdd,
    onDelete,
    onEdit
  }
}

export const userSave = () => {
  const tabStore = useTabStore()
  const dialogStore = useDialogStore()
  const route = useRoute()
  const router = useRouter()

  const id = ref(route.query?.id as string | undefined)

  const user = reactive<UserItemRequestData>({
    username: '',
    address: '',
    phone: '',
    realname: '',
    status: 'Active',
    avatar: '',
    email: ''
  })

  const { isLoading: pullUserLoading, execute: pullUserExecte } = useAsyncState(
    (id: string) =>
      getUser(id).then((u) => {
        Object.assign(user, u)
        return !!u.id
      }),
    true,
    { immediate: false, resetOnExecute: false }
  )

  if (id.value) {
    pullUserExecte(0, id.value)
  }

  const isEmail = ref(false)

  const action = import.meta.env.VITE_API_UPLOAD_URL

  const onBeforeUplaod = (rawFile: UploadRawFile) => {
    user.avatar = ''
    // 验证
    if (!ConfigImageExts.some((ext) => rawFile.name.endsWith(ext))) {
      ElNotification({
        message: `只允许 ${ConfigImageExts.join(' ')} 后缀`,
        type: 'error'
      })
      return false
    }

    if (rawFile.size > ConfigImageSize) {
      ElNotification({
        message: `文件过大`,
        type: 'error'
      })
      return false
    }

    // 预览图片
    const reader = new FileReader()
    reader.onload = (e) => {
      if (e.target?.result) {
        user.avatar = e.target?.result as string
      }
    }
    reader.readAsDataURL(rawFile)
  }

  const { isLoading, execute } = useAsyncState(
    () => (id.value ? updateUser(id.value, user) : addUser(user)),
    null,
    {
      immediate: false,
      resetOnExecute: false
    }
  )
  const onSave = async () => {
    await execute()
    ElNotification({
      message: '保存成功',
      type: 'success'
    })
    tabStore.close('user-save')
    router.push({ name: tabStore.tabActive })
  }

  const onDelete = () => {
    if (!id) {
      return
    }
    dialogStore.open(
      '删除提示',
      '确定要删除吗？',
      [
        { type: 'danger', label: '删除' },
        { type: 'default', label: '取消' }
      ],
      ($index) => {
        if ($index !== 0) {
          dialogStore.close()
          return
        }

        if (!id.value) {
          return
        }

        deleteUser(id.value).then(() => {
          dialogStore.close()
          ElNotification({
            message: '删除成功',
            type: 'success'
          })
          tabStore.close('user-save')
          router.push({ name: tabStore.tabActive })
        })
      }
    )
  }

  return {
    id,
    pullUserLoading,
    action,
    onBeforeUplaod,
    user,
    isEmail,
    onDelete,
    isLoading,
    onSave
  }
}
